package conf

import (
	"fmt"
	"log"
	"sync"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

func DefaultConfig() *Config {

	return &Config{
		Mysql:      *NewDefautlMysql(),
		HttpConfig: *NewHttp(),
	}
}

type Config struct {
	Mysql      Mysql      `json:"mysql"`
	HttpConfig httpConfig `json:"http_Config"`
}

type Mysql struct {
	Url          string
	Port         string
	Username     string
	PassWord     string
	Database     string
	MaxIdleConns int
	MaxOpenConns int

	//所有实例都会初始化并发程序，加锁最安全
	lock sync.Mutex
	db   *gorm.DB
}

// // fmt实现的包，让结构体答应出来更加规范
// func (c Config) String() string {
// 	d, _ := json.MarshalIndent(c, " ", " ")
// 	// fmt.Sprintf("%+v", c.Mysql.Database)
// 	return string(d)
// }

// 初始化db对象
func (m *Mysql) ORMDB() (*gorm.DB, error) {
	m.lock.Lock()
	defer m.lock.Unlock()
	//链接字符串组装
	if m.db == nil {
		dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True",
			m.Username, m.PassWord, m.Url, m.Port, m.Database)
		db, err := gorm.Open(mysql.Open(dsn),
			&gorm.Config{
				PrepareStmt:            true,
				SkipDefaultTransaction: true})
		if err != nil {
			log.Panicln("database was't running", err)
			return nil, err
		}

		//获取底层db
		sqlDB, err := db.DB()
		if err != nil {
			log.Panicln(err)
		}
		// SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
		sqlDB.SetMaxIdleConns(m.MaxIdleConns)
		// SetMaxOpenConns sets the maximum number of open connections to the database.
		sqlDB.SetMaxOpenConns(m.MaxOpenConns)
		// SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
		sqlDB.SetConnMaxLifetime(time.Hour)
		//ping数据库判断是否启动
		// err = sqlDB.Ping()
		// if err != nil {
		// 	log.Panicln("database was't running", err)
		// }
		m.db = db
		if err != nil {
			return nil, err
		}

	}

	return m.db, nil
}

func NewDefautlMysql() *Mysql {
	return &Mysql{
		Url:      "127.0.0.1",
		Port:     "3306",
		Username: "root",
		PassWord: "123456",
		Database: "vblog",
	}
}

func NewHttp() *httpConfig {
	return &httpConfig{
		Address: "127.0.0.1",
		Port:    "8081",
	}
}

type httpConfig struct {
	Address string `json:"address"`
	Port    string `json:"port"`
}

// 输出格式化
func (h *httpConfig) String() string {
	return fmt.Sprintf("%s:%s", h.Address, h.Port)
}
